package fr.bludwarf.commons.io;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.UUID;

import javax.xml.transform.stream.StreamSource;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.ConfigurationUtils;
import org.apache.commons.configuration.FileSystem;
import org.apache.commons.io.IOUtils;

public class FileUtils extends org.apache.commons.io.FileUtils
{
    public static final File CURRENT_FOLDER = new File(".");
	private static File _tempDir = null;

    /**
     * @param name
     * @param dir c'est un dossier qu'on veut créer ?
     * @return
     * @throws IOException
     * @throws ConfigurationException
     */
    public static File createTempFile(final String name, final boolean dir) throws IOException,
        ConfigurationException
    {
        if (_tempDir == null)
        {
//            if (DPConfProperties.getInstance().containsKey("temp"))
//            {
//                _tempDir = new File(DPConfProperties.getInstance().getString("temp"), "exs");
//                deleteDirectory(_tempDir);
//                _tempDir.mkdirs();
//            }
//            else
//            {
                _tempDir = File.createTempFile("platformizer-", "-tmp").getParentFile();
//            }
            
            _tempDir.deleteOnExit();
        }

        File tempFile = new File(_tempDir, name);

        // On crée un dossier unique pour éviter les collisions entre les fichiers/dossiers (export.xml, ...)
        while (tempFile.exists())
        {
            final File uniqueFolder = new File(_tempDir, UUID.randomUUID().toString());
            uniqueFolder.deleteOnExit();
            tempFile = new File(uniqueFolder, name);
        }

        // Dossier parent temporaire + création du chemin
        tempFile.getParentFile().deleteOnExit();
        tempFile.getParentFile().mkdirs();

        // Fichier ?
        if (!dir)
        {
            tempFile.createNewFile();
        }
        else
        {
            tempFile.mkdir();
        }

        // Temporaire
        tempFile.deleteOnExit();

        return tempFile;
    }

    /**
     * @param dir c'est un dossier qu'on veut créer ?
     * @return
     * @throws IOException
     * @throws ConfigurationException
     */
    public static File createTempFile(final boolean dir) throws IOException,
        ConfigurationException
    {
        return createTempFile(UUID.randomUUID().toString(), dir);
    }
    
    public static String readInputStreamToString(InputStream is) throws IOException
    {
        StringWriter writer = new StringWriter();
        IOUtils.copy(is, writer);
        return writer.toString();
    }
    
    /**
     * @see #readInputStreamToString(InputStream)
     */
    public static String readInputStreamToString(InputStream is, final String encoding) throws IOException
    {
        StringWriter writer = new StringWriter();
        IOUtils.copy(is, writer, encoding);
        return writer.toString();
    }
	
	/* TODO :
	public static InputStream getInputStreamFromString(String string)
    {
        return new ByteArrayInputStream(string.getBytes());
    }
	*/
    

    

    /**
     * Charge un fichier en le cherchant dans le classpath.
     * 
     * <p>
     * Si le fichier provient d'un JAR chargé manuellement il faut alors implémenter une copie de getResourceAsStream dans une des classe de ce JAR.
     * Le code de cette copie est alors :
     * </p>
     * <pre>
     * public static InputStream getResourceAsStream(final String filename) throws IOException
     * {
     *     return JARPropertiesConfiguration.getResourceAsStream(filename);
     * }
     * </pre>
     * 
     * @param filename chemin vers le fichier, sans le chemin du dossier source.
     * <p>
     * Exemple utiliser simplement "supervision/serviceTemplatesFromDPConf.xsl"
     * pour récupérer le fichier "src/main/xsl/supervision/serviceTemplatesFromDPConf.xsl"
     * </p>
     * @return
     * @throws IOException impossible de charger la ressource 
     */
    public static InputStream getResourceAsStream(final String filename) throws IOException
    {
        final URL url = getResource(filename);
        final FileSystem fs = FileSystem.getDefaultFileSystem();
        
        InputStream is;
        try
        {
            is = fs.getInputStream(url);
        }
        catch (ConfigurationException e)
        {
            throw new IOException(String.format(
                "Impossible de charger la ressource %s depuis la classe %s",
                filename,
                FileUtils.class.getName()), e);
        }
        
        if (is == null)
        {
            throw new IOException(String.format(
                "Impossible de trouver la ressource %s chargée depuis la classe %s",
                filename,
                FileUtils.class.getName()));
        }

        return is;
    }

    public static OutputStream getResourceAsOutputStream(final String filename) throws IOException
    {        
        final URL url = getResource(filename);
        final FileSystem fs = FileSystem.getDefaultFileSystem();
        
        OutputStream st;
        try
        {
            st = fs.getOutputStream(url);
        }
        catch (ConfigurationException e)
        {
            throw new IOException(String.format(
                "Impossible de charger la ressource %s depuis la classe %s",
                filename,
                FileUtils.class.getName()), e);
        }
        
        if (st == null)
        {
            throw new IOException(String.format(
                "Impossible de trouver la ressource %s chargée depuis la classe %s",
                filename,
                FileUtils.class.getName()));
        }

        return st;
    }
    
    /**
     * @param filename chemin vers le fichier, sans le chemin du dossier source.
     * <p>
     * Exemple utiliser simplement "supervision/serviceTemplatesFromDPConf.xsl"
     * pour récupérer le fichier "src/main/xsl/supervision/serviceTemplatesFromDPConf.xsl"
     * </p>
     * @return
     * @throws ConfigurationException impossible de charger la ressource 
     */
    public static StreamSource getResourceAsStreamSource(final String filename) throws IOException
    {
        final InputStream is = getResourceAsStream(filename);

        // Stream Source
        final StreamSource src = new StreamSource(is);
        src.setSystemId(filename);

        return src;
    }
    
    // FIXME : à tester
    public static boolean resourceExists(final String filename)
    {
    	return getResource(filename) != null;
    }

    public static URL getResource(final String filename)
    {
        return ConfigurationUtils.locate(filename);
    }

	/**
	 * @param filename
	 * @return
	 * @throws IOException
	 * 
	 * @see {@link #readFileToString(File)}
	 */
	public static String readFileToString(final String filename) throws IOException
	{
		final URL resource = getResource(filename);
		final File file = new File(resource.getFile());
		return readFileToString(file);
	}

	/**
	 * @param filename
	 * @return
	 * @throws IOException
	 * 
	 * @see {@link #readInputStreamToString(InputStream)}
	 */
	public static String readResourceToString(final String resource) throws IOException
	{
		final InputStream input = getResourceAsStream(resource);
		return readInputStreamToString(input);
	}

	/**
	 * @see #readResourceToString(String)
	 */
	public static String readResourceToString(final String resource, final String charset) throws IOException
	{
		final InputStream input = getResourceAsStream(resource);
		return readInputStreamToString(input, charset);
	}
}

